from zhipuai import ZhipuAI
import re
import inspect
import json
import pymysql
import pandas as pd


api_key = "4956db3da95d43eab77efa6937882679.Xm27NhBWZPJE3ORb"
client = ZhipuAI(api_key=api_key)

def extract_function_code(s_python,detail=0):
    """
    函数提取函数，同时执行函数内容，可以选择打印函数信息
    """

    def extract_code(s_python):
        """
                如果输入的字符串s是一个包含Python代码的Markdown格式字符串，提取出代码部分。
                否则，返回原字符串。

                参数:
                s: 输入的字符串。

                返回:
                提取出的代码部分，或原字符串。
                """
        # 判断字符串是否是Markdown格式
        if "```python" in s_python or "Python" in s_python or "PYTHON" in s_python:
            start = s_python.find("def")
            end = s_python.find("```\n",start)
            code = s_python[start:end]
        else:
            code = s_python
        return code

    code = extract_code(s_python)
    # 提取函数名称
    match = re.search(r"def (w\+)",code)
    function_name = match.group(0)

    # 将函数写入本地
    with open(r"F:\ai\03大模型开发实战\08 低代码智能开发平台案例实践\%s.py" % function_name, "w", encoding="utf8") as f:
        f.write(code)

    # 执行该函数
    try:
        exec(code, globals())
    except Exception as e:
        print("An error occurred while executing the code:")
        print(e)

    # 打印函数名称
    if detail == 0:
        print(function_name)

    if detail == 1:
        with open(r"F:\ai\03大模型开发实战\08 低代码智能开发平台案例实践\%s.py" % function_name, "r",
                  encoding="utf8") as f:
            current_code_content = f.read()
            print(current_code_content)


def auto_functions(functions_list):
    """
    Chat模型的functions参数编写函数
    :param functions_list: 包含一个或者多个函数对象的列表；
    :return：满足Chat模型functions参数要求的functions对象
    """
    def functions_generate(functions_list):
        # 创建空列表，用于保存每个函数的描述字典
        functions = []
        # 对每个外部函数进行循环
        for function in functions_list:
            # 读取函数对象的函数说明
            function_description = inspect.getdoc(function)
            # 读取函数的函数名字符串
            function_name = function.__name__
            ## one-shot
            system_prompt1="""输出结果必须是一个JSON格式的字典,举个例子：
            [{'type': 'function', 'function': {'name': 'sunwukong_function', 'description': '该函数定义了数据集计算过程，接收一个数据表字符串参数，并返回一个JSON格式的Dataframe类型对象。', 'parameters': {'type': 'object', 'properties': {'data': {'type': 'string', 'description': '带入计算的数据表，用字符串进行表示'}}, 'required': ['data'], 'additionalProperties': False}}}]
            """
            system_prompt2 = '以下是某的函数说明：%s,输出结果必须是一个JSON格式的字典，只输出这个字典即可，前后不需要任何前后修饰或说明的语句' % function_description
            user_prompt = '根据这个函数的函数说明，请帮我创建一个JSON格式的字典，这个字典有如下5点要求：\
                           1.字典总共有三个键值对；\
                           2.第一个键值对的Key是字符串name，value是该函数的名字：%s，也是字符串；\
                           3.第二个键值对的Key是字符串description，value是该函数的函数的功能说明，也是字符串；\
                           4.第三个键值对的Key是字符串parameters，value是一个JSON Schema对象，用于说明该函数的参数输入规范。\
                           5.输出结果必须是一个JSON格式的字典，只输出这个字典即可，前后不需要任何前后修饰或说明的语句' % function_name

            response = client.chat.completions.create(
                              model="glm-4",
                              messages=[
                                {"role": "system", "content": system_prompt1},
                                {"role": "system", "content": system_prompt2},
                                {"role": "user", "content": user_prompt}
                              ]
                            )
            json_str=response.choices[0].message.content.replace("```json","").replace("```","")
            json_function_description=json.loads(json_str)
            json_str={"type": "function","function":json_function_description}
            functions.append(json_str)
        return functions
    ## 最大可以尝试4次
    max_attempts = 4
    attempts = 0

    while attempts < max_attempts:
        try:
            functions = functions_generate(functions_list)
            break  # 如果代码成功执行，跳出循环
        except Exception as e:
            attempts += 1  # 增加尝试次数
            print("发生错误：", e)
            if attempts == max_attempts:
                print("已达到最大尝试次数，程序终止。")
                raise  # 重新引发最后一个异常
            else:
                print("正在重新运行...")
    return functions

def retrieve_emails(n,user_id = "me"):
    """
        获取指定数量的最近邮件。
        参数:
        n: 要检索的邮件的数量,数据格式为int类型。
        user_id: 要检索邮件的用户的ID。默认值是'me'，数据格式为字符串类型。

        返回:
        一个列表，其中每个元素都是一个字典，表示一封邮件。每个字典包含以下键：
        'from_userid': 发件人ID。
        'date': 邮件的发送日期。
        'subject': 邮件的主题。
        'snippet': 邮件的摘要（前100个字符）。
    """
    connect = pymysql.connect(host="localhost",
                              port=3306,
                              user="root",
                              passwd="1qaz2wsx",
                              charset="utf8",
                              db="my_mail")

    sql_query = f"SELECT * FROM mailbox WHERE userid = '{user_id}' ORDER BY date DESC LIMIT {n}";

    try:
        with connect.cursor() as cursor:
            cursor.execute(sql_query)
            results = cursor.fetchall()
    finally:
        cursor.close()

    column_names = [desc[0] for desc in cursor.description]

    df = pd.DataFrame(results,columns=column_names)

    return df.to_json(orient="records")

def get_latest_email(userid="me"):
    """
        获取最新的一封邮件
        参数:
        user_id: 要检索邮件的用户的ID。默认值是'me'，数据格式为字符串类型。

        返回:
        一个列表，其中每个元素都是一个字典，表示一封邮件。每个字典包含以下键：
        'from_userid': 发件人ID。
        'date': 邮件的发送日期。
        'subject': 邮件的主题。
        'snippet': 邮件的摘要（前100个字符）。
    """
    mysql_pw = "gpt"

    connection = pymysql.connect(
        host='localhost',  # 数据库地址
        user='gpt',  # 数据库用户名
        passwd=mysql_pw,  # 数据库密码
        db='my_mail',  # 数据库名
        charset='utf8'  # 字符集选择utf8
    )
    sql_query = f"SELECT * FROM mailbox WHERE userid = '{userid}' ORDER BY date DESC LIMIT 1";

    try:
        with connection.cursor() as cursor:
            sql = sql_query
            cursor.execute(sql)
            results = cursor.fetchall()
    finally:
        cursor.close()

    column_names = [desc[0] for desc in cursor.description]

    # 使用results和column_names创建DataFrame
    df = pd.DataFrame(results, columns=column_names)

    return df.to_json(orient="records")

def get_email_count(userId='me'):
    """
    获取指定用户邮箱中的邮件总数。

    参数:
    userId: 要查询的用户的ID。默认值是'me'，数据格式为字符串类型。

    返回:
    一个JSON格式对象，包含一个键值对，键为'count'，值为邮件总数。

    示例:
    {
        "count": 123
    }
    """

    # 数据库连接配置
    config = {
        'host': 'localhost',
        'user': 'gpt',
        'passwd': 'gpt',
        'db': 'my_mail',
        'charset': 'utf8'
    }

    # 建立数据库连接
    try:
        connection = pymysql.connect(**config)
        with connection.cursor() as cursor:
            # 查询邮件总数
            sql = f"SELECT COUNT(*) FROM mailbox WHERE userid = '{userId}'"
            cursor.execute(sql)
            result = cursor.fetchone()
            email_count = result[0] if result else 0

            # 将结果转换为JSON格式
            return json.dumps({'count': email_count})
    except pymysql.MySQLError as e:
        print(f"数据库操作出错: {e}")
        return json.dumps({'error': str(e)})
    finally:
        if connection:
            connection.close()

function_list = [retrieve_emails,get_email_count,get_latest_email]

# functions = auto_functions(function_list)

with open(r"F:\ai\03大模型开发实战\08 低代码智能开发平台案例实践\资料\my_mail数据字典.md","r",encoding="utf8") as f:
    md_content = f.read()

messages = [{"role":"system","content":md_content,
    "role":"user","content":"请帮我查询下是否有来自陆小凤的未读邮件，有的话帮我解析下邮件类型"}]

# response = client.chat.completions.create(model="glm-4",
#                                           messages=messages,
#                                           tools=functions,
#                                           tool_choice="auto")
# print(response)



get_email_input = "请帮我查询一下邮箱里的最后一封邮件"

get_email_output = "请帮我编写一个python函数，用于获取邮箱中的最后一封邮件，函数的内容格式要求如下:\
                    1.函数的参数userid，userid是一个字符串类型的参数，默认情况下取值'me'，表示查看我的邮件\
                    2.函数的返回结果是一个包含最后一封邮件信息的对象，该对象的格式必须是json格式\
                    3.请将全部功能封装在一个函数内\
                    4.请在编写函数的过程中，在函数内部加入中文编写的详细说明文档，用于说明函数功能、函数参数情况和函数返回结果等信息"

count_email_input = "请帮我查询下邮箱里现在一共有多少封邮件"

count_email_output = "请帮我编写一个python函数，用于获取邮箱里一共有多少封邮件，函数的内容格式要求如下:\
                      1.函数的参数userid，userid是一个字符串类型的参数，默认情况下取值'me'，表示查看我的邮件\
                      2.函数的返回结果是一个包含一共有多少封邮件的对象，该对象的格式必须是json格式\
                      3.请将全部功能封装在一个函数内\
                      4.请在编写函数的过程中，在函数内部加入中文编写的详情说明文档，用于说明函数功能、函数参数情况和函数返回结果等信息"

message_fewshot_stage1 = [{"role":"system","content":f"最后输出的是一个说明，举个例子，输出的格式如下:{count_email_output}"},
                          {"role":"system","content":"请模仿下列对话给出的风格，基于我的问题，把我的问题转换为一个说明。注意，不需要额外的输出"},
                          {"role":"user","name":"exampl1_user","content":get_email_input},
                          {"role":"assistant","name":"exampl1_assistant","content":get_email_output},
                          {"role":"user","name":"exampl2_user","content":count_email_input},
                          {"role":"assistant","name":"exampl2_assistant","content":count_email_output},
                          {"role":"user","content":"请帮我查询下是否有来自陆小凤的未读邮件，并解读最近一封未读邮件的内容"}]

resp = client.chat.completions.create(model="glm-4",messages=message_fewshot_stage1)
stage1_content = resp.choices[0].message.content
print(resp.choices[0].message.content)

with open(r"E:\dev\aistudy\pythonProject\testAi\get_latest_email.py","r",encoding="utf8") as f:
    latest_email_content = f.read()

# print(latest_email_content)

system_content2 = "你是一个擅长写代码的智能助手，代码写完后，不用给出代码的调用示例，也不要有除代码外的额外的输出，只需要输出代码即可。"

message_code = [{"role":"system","content":md_content},
                {"role":"system","content":system_content2},
                {"role":"user","name":"user_example","content":get_email_output},
                {"role":"assistant","name":"assistant_example","content":latest_email_content},
                {"role":"user","content":stage1_content}]

resp_code = client.chat.completions.create(model="glm-4",
                                           messages=message_code)
code_ai = resp_code.choices[0].message.content
print(code_ai)



